#include <windows.h>
#include <stdio.h>

HANDLE hStdin;
DWORD fdwSaveOldMode;

VOID ErrorExit(LPSTR);
VOID KeyEventProc(KEY_EVENT_RECORD);
VOID MouseEventProc(MOUSE_EVENT_RECORD);
VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);

int main(VOID)
{
	DWORD cNumRead, fdwMode, i;
	INPUT_RECORD irInBuf[128];
	int counter = 0;

	//Get the standard input handle.

	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	if(hStdin == INVALID_HANDLE_VALUE)
		ErrorExit("GetStdHandle");

	// Save the current input mode. to be restored on exit.

	if (! GetConsoleMode(hStdin, &fdwSaveOldMode) )
		ErrorExit("GetConsoleMode");

	//Enable the window ad mouse input events.
	fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
	if(! SetConsoleMode(hStdin, fdwMode))
		ErrorExit("SetConsoleMode");

	//Loop to read and handle the next 100 inout events.

	while(counter++ <= 100)
	{
		//wait fir the events.

		if(! ReadConsoleInput(
				hStdin, //input buffer handle
				irInBuf,//buffer to read info
				128, //size if read buffer
				&cNumRead)) //number of record read
			ErrorExit("ReadConsoleInput");

		//Dispath th events to the appropriate handler.

		for(i = 0; i < cNumRead; i++)
		{
			switch(irInBuf[i].EventType)
			{
				case KEY_EVENT: //keyboard input
					KeyEventProc(irInBuf[i].Event.KeyEvent);
					break;
				case MOUSE_EVENT: //MOUSE INPUT
					MouseEventProc(irInBuf[i].Event.MouseEvent);
					break;
				case WINDOW_BUFFER_SIZE_EVENT: //scrn buf. resizing
					ResizeEventProc(irInBuf[i].Event.WindowBufferSizeEvent);
					break;
				case FOCUS_EVENT: //disregard focus event
					
				case MENU_EVENT:
					break;

				default:
					ErrorExit("Unknow event type");
					break;
			}
		}
	}

	//Restore input mode on exit

	SetConsoleMode(hStdin, fdwSaveOldMode);

	return 0;
}

VOID ErrorExit(LPSTR lpszMessage)
{
	fprintf(stderr, "%s\n",lpszMessage);

	//Restore input mode on exit

	SetConsoleMode(hStdin, fdwSaveOldMode);

	ExitProcess(0);
}

VOID KeyEventProc(KEY_EVENT_RECORD ker)
{
	printf("key event: ");

	if(ker.bKeyDown)
		printf("Key pressed \n");
	else printf("key released\n");
}

VOID MouseEventProc(MOUSE_EVENT_RECORD mer)
{
#ifndef MOUSE_HWHEELED;
#define MOUSE_HWHEELED 0X0008;
#endif
	printf("Mouse event: ");

	switch(mer.dwEventFlags)
	{
		case 0:
			if(mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
			{
				printf("left button press \n");
			}
			else if(mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
			{
				printf("right button press\n");
			}
			else
			{
				printf("button press\n");
			}
			break;

		case DOUBLE_CLICK:
			printf("double click\n");
			break;
		case MOUSE_HWHEELED:
			printf("horizontal mouse wheel\n");
			break;
		case MOUSE_MOVED:
			printf("mouse moved\n");
		case MOUSE_WHEELED:
			printf("vertical mouse wheel\n");
			break;
		default:
			printf("unknow\n");
			break;
	}
}

VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD wbsr)
{
	printf("Resize event\n");
	printf("Console screen buffer is %d colums by %d row.\n",wbsr.dwSize.X,wbsr.dwSize.Y);
}